package com.bbva.kyfb.kyfbbofi;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.bbva.jee.arq.spring.core.gce.ExcepcionEjecucionAplicacion;
import com.bbva.jee.arq.spring.core.log.I18nLog;
import com.bbva.jee.arq.spring.core.log.I18nLogFactory;
import com.bbva.kyfb.kyfbdto.firmas.bo.FicheroInfo;
import com.bbva.kyfb.kyfbdto.firmas.bo.FicheroPdteFirma;
import com.bbva.kyfb.kyfbdto.firmas.bo.FirmanteInfo;
import com.bbva.kyfb.kyfbdto.firmas.errores.Errores_kyfb_servicios;
import com.bbva.kyfb.kyfbofi.objects.Cuentas;
import com.bbva.kyfb.kyfbutils.constantes.ConstantesFO;
import com.bbva.kyfb.kyfbutils.constantes.UtilFO;
import com.bbva.kyfb.kyfbutils.invoker.InvokerUtils;
import com.bbva.kyfb.kyfbutils.invoker.ServicioFirmasInvokerComun;
import com.bbva.kygu.clientcontractws.beans.AUsuarioServAsuntoType;
import com.bbva.kygu.clientcontractws.beans.RespuestaServicioCtxType;
import com.bbva.kygu.clientcontractws.beans.UsuarioServAsuntoType;
import com.bbva.kytv.dto.kygu.UsuarioEmpresaDTO;
import com.bbva.kytv.interfaces.kygu.IGestionLimite;
import com.bbva.kytv.interfaces.kygu.IInformacionEmpresaInvoker;
import com.bbva.kytv.interfaces.kygu.IInformacionUsuarios;
import com.bbva.kytv.util.exception.KYTVException;

/**
 * The Class ServicioFirmasBoClientsUtil.
 */
@Component("servicioFirmasBoClientsUtil")
public class ServicioFirmasBoClientsUtil extends ServicioFirmasInvokerComun {

	private static final I18nLog LOG = I18nLogFactory
			.getLogI18n(ServicioFirmasBoClientsUtil.class);

	private static final String[] ASUN_OPT1 = { "AAC", "ACM", "ACO", "ACR", "CFV", "CPA", "CPS"};
	private static final String[] ASUN_OPT2 = { "GDL", "GDP", "GLD", "GPD", "OMO" };
	private static final String[] ASUN_OPT3 = { "ACP", "CPR", "CVP", "DOO", "GDS", "IDC", "JBE", "JBR",
		"MCP", "MCR", "MRC", "RDC", "RDJ", "RDM", "RDO", "SFI" };
	private static final String[] ASUN_OPT4 = { "FAA", "FPN", "FRN" };
	private static final String[] ASUN_OPT5 = { "FAI", "FPI", "FRT", "FSI", "TRR" };
	private static final String[] ASUN_OPT6 = { "ACC", "ACV", "CVC", "CVV", "CVW", "MCC", "MCV", "MCW" };
	private static final String[] ASUN_OPT7 = { "BTJ", "CDP", "CHP", "DSD", "EFE", "GMS", "ISG", "JU1",
		"PIC", "PIP", "PSC", "PSP", "TRI", "VIV", "VVE" };

	static{
		// En principio se han guardado ordenados pero se reordenan por seguridad.
		// Si no estan ordenados el binary search no funciona adecuadamente
		Arrays.sort(ASUN_OPT1);
		Arrays.sort(ASUN_OPT2);
		Arrays.sort(ASUN_OPT3);
		Arrays.sort(ASUN_OPT4);
		Arrays.sort(ASUN_OPT5);
		Arrays.sort(ASUN_OPT6);
		Arrays.sort(ASUN_OPT7);
	}

	/** The servicio firmas bo util. */
	@Autowired
	private ServicioFirmasBoUtil servicioFirmasBoUtil;

	/**
	 * Gets the apoderados servicio.
	 * 
	 * @param fichero
	 *            the fichero
	 * @param file
	 *            the file
	 * @param codServicio
	 *            the cod servicio
	 * @return the apoderados servicio
	 * @throws ExcepcionEjecucionAplicacion
	 *             the excepcion ejecucion aplicacion
	 */
	public List<UsuarioServAsuntoType> getApoderadosServicio(
			final FicheroPdteFirma fichero, final FicheroInfo file,
			final String codServicio) throws ExcepcionEjecucionAplicacion {
		final String indOrdenanteBeneficiario = UtilFO.ORDENANTE_BENEFICIARIO;
		final Map<String, String> hashNombreUsuario = new HashMap<String, String>();
		final String codCanal = file.getCodClienteCash().substring(0, 4);
		final int codBancoInterno = Integer.parseInt(file.getCodClienteCash()
				.substring(4, 8));
		final String codEmpresa = file.getCodClienteCash().substring(8, 16);
		final int codBancoProducto = Integer.parseInt(file.getsBancoProducto());
		final int codSubProducto = Integer.parseInt(file.getsCodSubproducto());
		final int codProducto = Integer.parseInt(file.getsCodProducto());
		//final int bancoAsunto = Integer.parseInt(file.getsBancoAsunto());
		final String nuAsunto = transformarAsunto(fichero, file);
		final double importe = fichero.getdImporte().doubleValue();
		final String divisa = fichero.getsDivisa();
		final IGestionLimite gestionLimite = (IGestionLimite) InvokerUtils
				.getBeanInvoker(ConstantesFO.VAR_GESTION_LIMITE,
						IGestionLimite.class);
		com.bbva.kygu.clientcontractws.beans.RespuestaUsuarioServAsuntoType respuesta = null;

		try {

			respuesta = gestionLimite.listarUsuariosApodFirmantes(codCanal,
					codBancoInterno, codEmpresa, codBancoProducto, codProducto,
					codSubProducto, codServicio, indOrdenanteBeneficiario,
					codBancoInterno, nuAsunto, importe, divisa);

		} catch (final KYTVException e) {
			throw new ExcepcionEjecucionAplicacion(
					Errores_kyfb_servicios.SERVICIO_NO_DISPONIBLE, e);
		}

		final AUsuarioServAsuntoType usuariosApoderados = respuesta
				.getListaUsuarioServ();
		final List<UsuarioServAsuntoType> listaAuxiliar = new ArrayList<UsuarioServAsuntoType>();
		final List<UsuarioServAsuntoType> listaUsuarios = usuariosApoderados != null && usuariosApoderados.getUsuarioServAsunto() != null ? usuariosApoderados.getUsuarioServAsunto() : new ArrayList<UsuarioServAsuntoType>();
		if (!listaUsuarios.isEmpty()) {

			List<UsuarioEmpresaDTO> res = null;
			try {
				final IInformacionUsuarios infoUsuarios = (IInformacionUsuarios) InvokerUtils
						.getBeanInvoker(ConstantesFO.VAR_LISTA_USUARIO,
								IInformacionUsuarios.class);
				res = infoUsuarios.listarUsuariosPorTipoPerfil(codCanal,
						codBancoInterno, codEmpresa, codBancoProducto,
						codProducto, codSubProducto, "", "S", "", "", "");
			} catch (final KYTVException e) {
				throw new ExcepcionEjecucionAplicacion(
						Errores_kyfb_servicios.SERVICIO_NO_DISPONIBLE, e);
			}

			for (final UsuarioEmpresaDTO usuarioType : res) {
				hashNombreUsuario.put(usuarioType.getCodUsuario(),
						usuarioType.getNomUsuario());
			}
		}
		for (final UsuarioServAsuntoType usuario : listaUsuarios) {
			if (usuario != null
					&& !StringUtils.isEmpty(usuario.getTipoFirmante())) {
				if (hashNombreUsuario.containsKey(usuario.getCodUsuario())) {
					usuario.setNomUsuario(hashNombreUsuario.get(usuario
							.getCodUsuario()));
				}
				listaAuxiliar.add(usuario);
			}
		}

		return listaAuxiliar;
	}

	/**
	 * Adds the auditores to lista firmantes.
	 * 
	 * @param file
	 *            the file
	 * @param listaFirmantes
	 *            the lista firmantes
	 * @param ficheroPdte
	 *            the fichero pdte
	 * @throws ExcepcionEjecucionAplicacion
	 *             the excepcion ejecucion aplicacion
	 */
	public void addAuditoresToListaFirmantes(final FicheroInfo file,
			final List<FirmanteInfo> listaFirmantes,
			final FicheroPdteFirma ficheroPdte,
			final Map<String, String> numerosAleatorios)
					throws ExcepcionEjecucionAplicacion {
		final List<UsuarioEmpresaDTO> listaUsuariosAuditores = getAuditoresReferencia(
				ficheroPdte, file, file.getCodClienteCash());
		FirmanteInfo auditor;
		for (final UsuarioEmpresaDTO usuarioAuditor : listaUsuariosAuditores) {
			auditor = new FirmanteInfo();
			auditor.setCodUsuario(usuarioAuditor.getCodUsuario());
			auditor.setsTipoFirma(usuarioAuditor.getModFirma());
			auditor.setsTipoFirmante(usuarioAuditor.getTipoFirmante());
			auditor.setPoderFirma(UtilFO.FIRMA_SOLIDARIO);
			auditor.setsNomUsuario(usuarioAuditor.getNomUsuario());
			ficheroPdte.setsPoderFirma(auditor.getPoderFirma());
			auditor.setNumeroAleatorio(servicioFirmasBoUtil
					.asignarNumeroAleatorio(numerosAleatorios, ficheroPdte,
							file, auditor.getCodUsuario()));
			listaFirmantes.add(auditor);
		}
	}

	/**
	 * Transforma el String del asunto en funcion del codigo clase orden.
	 * 
	 * @param fichero
	 *            the fichero
	 * @param file
	 *            the file
	 * @return Devuelve String del asunto con las transformaciones necesarias
	 */
	public String transformarAsunto(final FicheroPdteFirma fichero,
			final FicheroInfo file) {
		String cuenta = fichero.getsAsunto().trim();
		final String normalizedCodOrden = fichero.getsCodTipoOrden().trim().toUpperCase();
		final Cuentas cta = new Cuentas();

		try {
			if (normalizedCodOrden.equals("VAL")) {
				cuenta = cta.iban(cuenta,0,4,5,9,14,16,16,-1);
			} else if (Arrays.binarySearch(ASUN_OPT1,normalizedCodOrden)>-1) {
				// Para Anticipos de Confirming Proveedores (ACO, ACR, ACM),
				// anticipos Confirming Portugal (CPS)
				// y para Anulacion de Anticipos de Confirming (AAC) y anulacion
				// de anticipos Confirming Portugal (CPA),
				// el Asunto contratado es el primero que exista en la tabla SER
				// para el Servicio 204
				final String codCanal = file.getCodClienteCash().substring(0, 4);
				final int codBancoInterno = Integer.parseInt(file.getCodClienteCash().substring(4, 8));
				final String codEmpresa = file.getCodClienteCash().substring(8,16);
				final int codBancoProducto = Integer.parseInt(file.getsBancoProducto());
				final int codSubProducto = Integer.parseInt(file.getsCodSubproducto());
				final int codProducto = Integer.parseInt(file.getsCodProducto());

				final IInformacionEmpresaInvoker infoEmpresa = (IInformacionEmpresaInvoker) InvokerUtils
						.getBeanInvoker(ConstantesFO.VAR_INFO_EMPRESA,
								IInformacionEmpresaInvoker.class);
				final RespuestaServicioCtxType respuesta = infoEmpresa
						.listarServiciosAsuntos(codCanal, codBancoInterno,
								codEmpresa, codBancoProducto, codProducto,
								codSubProducto,
								fichero.getCodigoServicioGlobal(), "", "O",
								Integer.MIN_VALUE, "", "S", "", "");

				cuenta = respuesta.getListaServicioCtx().getServicioCtx()
						.get(0).getListaAsunto().getAsunto().get(0)
						.getNuAsunto();

				//			} else if (normalizedCodOrden.equals("OMO")) { Se mete dentro de ASUN_OPT2
				//				// Transferencias Banco de Espana on-line
				//				cuenta = cta.iban(cuenta.substring(0, 4), cuenta.substring(4, 8),
				//						cuenta.substring(10, 13), cuenta.substring(13, cuenta.length()-1));

			} else if (Arrays.binarySearch(
					ASUN_OPT2,normalizedCodOrden)>-1) {
				// Gestion de limites de la Generalitat
				cuenta = cta.iban(cuenta,0,4,4,8,10,13,13,-1);

			} else if (Arrays.binarySearch(ASUN_OPT3,normalizedCodOrden)>-1) {
				// Mira por si ponemos en no CDI
				cuenta = "";
				// Integracion de fondos CASH
			} else if (Arrays.binarySearch(ASUN_OPT4,normalizedCodOrden)>-1) {
				// para las cuentas de fondos nacionales, no se modifica
				cuenta = cuenta.replaceAll("-810-", "-");
				// } else if (normalizedCodOrden.equalsIgnoreCase("FSN")){ Con
				// este caso ya no se hace nada
				// cuenta=cta.iban(new
				// Integer(cuenta.substring(0,4)).intValue(),new
				// Integer(cuenta.substring(5,9)).intValue(),
				// new Integer(cuenta.substring(13,16)).intValue(), new
				// Long(cuenta.substring(16,cuenta.length()-1)).longValue());
				// Trace.trace(Trace.Error,"Suscripcion nacional");
			} else if (Arrays.binarySearch(ASUN_OPT5,normalizedCodOrden)>-1) {
				cuenta = cuenta.replaceAll("-930-", "-");
			} else if (Arrays.binarySearch(ASUN_OPT6,normalizedCodOrden)>-1) {
				cuenta = new StringBuilder(cuenta).insert(4, '-').insert(9, '-').delete(10, 17).toString();
			} else if (Arrays.binarySearch(ASUN_OPT7,normalizedCodOrden)<0) {
				cuenta = cta.iban(cuenta,0,4,5,9,13,16,16,-1);

			}
		} catch (final NullPointerException ex) {
			// No se hace nada, se retorna la cuenta (asunto.trim())
			LOG.info(ex, "getTipoFirmante", file);
		} catch (final IndexOutOfBoundsException ex) {
			// No se hace nada, se retorna la cuenta (asunto.trim())
			LOG.info(ex, "getTipoFirmante", file);
		} catch (final NumberFormatException ex) {
			// No se hace nada, se retorna la cuenta (asunto.trim())
			LOG.info(ex, "getTipoFirmante", file);
		}

		return cuenta;
	}

}
